#include "ql.h"
#include <ql/quantlib.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/unordered_map.hpp>
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/timer.hpp>
#include <iostream>
#include <iomanip>
#include <string>

using namespace std;
using namespace QuantLib;

int TestCalendar();
int TestBond();
int TestCDS();
int TestSwap();
int TestFra();
int TestSwaption();
int TestRepo();

int main(int, char* [])
{
	//test back to demo
	
	//TestCalendar();

	//TestBond();
	
	//TestCDS();
	
	TestSwap();
	
	//TestFra();

	//TestSwaption();

	//TestRepo();
}

int TestCalendar()
{
	try 
	{


	
	} 
	catch (std::exception& e) 
	{
		std::cerr << e.what() << std::endl; 
	} 
	catch (...) 
	{
		std::cerr << "unknown error" << std::endl;
	}

	return 0;
}

int TestBond()
{
	try 
	{
			Calendar calendar = TARGET();
			Date settlementDate(18, September, 2008);
			settlementDate = calendar.adjust(settlementDate);
			Integer fixingDays = 3;
			Natural settlementDays = 3;
			Date todaysDate = calendar.advance(settlementDate, -fixingDays, Days);

			ql qlProxy;

			//market
			std::string mkt = qlProxy.MarketSet("Mkt_", todaysDate.serialNumber() );
		
			std::string indx1 = qlProxy.Index("Mkt_", "SwapCurve", "USDLibor3M", "USDLibor", "3M", "39646,0.0278625");
			std::string indx2 = qlProxy.Index("Mkt_", "EURCurve", "Euribor6M", "Euribor", "6M", "");

			//swap curve
			std::stringstream srate;
			srate << qlProxy.DepoRate("Mkt_","Depo1W", 0.043375, "1W", 3, "Act/360", "ModifiedFollowing", "TGT") << ",";
			srate << qlProxy.DepoRate("Mkt_","Depo1M", 0.031875, "1M", 3, "Act/360", "ModifiedFollowing", "TGT") << ",";
			srate << qlProxy.DepoRate("Mkt_","Depo3M", 0.0320375, "3M", 3, "Act/360", "ModifiedFollowing", "TGT") << ",";
			srate << qlProxy.DepoRate("Mkt_","Depo6M", 0.03385, "6M", 3, "Act/360", "ModifiedFollowing", "TGT") << ",";
			srate << qlProxy.DepoRate("Mkt_","Depo9M", 0.0338125, "9M", 3, "Act/360", "ModifiedFollowing", "TGT") << ",";
			srate << qlProxy.DepoRate("Mkt_","Depo1Y", 0.0335125, "1Y", 3, "Act/360", "ModifiedFollowing", "TGT") << ",";
			srate << qlProxy.SwapRate("Mkt_","Swap2Y", 0.0295, "2Y", 3, 1, "Euribor6M", "Annual", "Euro30/360","Unadjusted","TGT") << ",";
			srate << qlProxy.SwapRate("Mkt_","Swap3Y", 0.0323, "3Y", 3, 1, "Euribor6M", "Annual", "Euro30/360","Unadjusted","TGT") << ",";
			srate << qlProxy.SwapRate("Mkt_","Swap5Y", 0.0359, "5Y", 3, 1, "Euribor6M", "Annual", "Euro30/360","Unadjusted","TGT") << ",";
			srate << qlProxy.SwapRate("Mkt_","Swap10Y", 0.0412, "10Y", 3, 1, "Euribor6M", "Annual", "Euro30/360","Unadjusted","TGT") << ",";
			srate << qlProxy.SwapRate("Mkt_","Swap15Y", 0.0433, "15Y", 3, 1, "Euribor6M", "Annual", "Euro30/360","Unadjusted","TGT");
			std::string scurve = qlProxy.YieldCurve("Mkt_", "SwapCurve", "SwapCurve", settlementDate.serialNumber(), srate.str(), "Act/Act:ISDA", 0, "TGT");

			//bond curve
			std::stringstream brates;
			brates << qlProxy.DepoRate("Mkt_","Zcm3M", 0.0096, "3M", 3, "Act/365:Fixed", "ModifiedFollowing", "TGT") << ",";
			brates << qlProxy.DepoRate("Mkt_","Zcm6M", 0.0145, "6M", 3, "Act/365:Fixed", "ModifiedFollowing", "TGT") << ",";
			brates << qlProxy.DepoRate("Mkt_","Zcm1Y", 0.0194, "1Y", 3, "Act/365:Fixed", "ModifiedFollowing", "TGT") << ",";
			brates << qlProxy.FixedRateBondBuild("Mkt_", "Bond0", 0.02375, 100.390625, "Semiannual", 100, 3, Date(15, March, 2005).serialNumber(),  Date (31, August, 2010).serialNumber(),"Act/Act:Bond","Unadjusted","Unadjusted","Unadjusted", "USD:Govt") << ","; 
			brates << qlProxy.FixedRateBondBuild("Mkt_", "Bond1", 0.04625, 106.21875, "Semiannual", 100, 3, Date(15, June, 2005).serialNumber(), Date(31, August, 2011).serialNumber(),"Act/Act:Bond","Unadjusted","Unadjusted","Unadjusted", "USD:Govt") << ","; 
			brates << qlProxy.FixedRateBondBuild("Mkt_", "Bond2", 0.03125, 100.59375, "Semiannual", 100, 3, Date(30, June, 2006).serialNumber(), Date(31, August, 2013).serialNumber(),"Act/Act:Bond","Unadjusted","Unadjusted","Unadjusted", "USD:Govt") << ","; 
			brates << qlProxy.FixedRateBondBuild("Mkt_", "Bond3", 0.04000, 101.6875, "Semiannual", 100, 3, Date(15, November, 2002).serialNumber(), Date(15, August, 2018).serialNumber(),"Act/Act:Bond","Unadjusted","Unadjusted","Unadjusted", "USD:Govt") << ","; 
			brates << qlProxy.FixedRateBondBuild("Mkt_", "Bond4", 0.04500, 102.140625, "Semiannual", 100, 3, Date(15, May, 1987).serialNumber(), Date (15, May, 2038).serialNumber(),"Act/Act:Bond","Unadjusted","Unadjusted","Unadjusted", "USD:Govt"); 
			std::string bcurve = qlProxy.BondCurve("Mkt_", "BondCurve", "SwapCurve", settlementDate.serialNumber(), brates.str(), "Act/Act:ISDA", 0, "TGT");		

			//bonds to price 
 			std::string bondA = qlProxy.ZeroCouponBondBuild("Mkt_", "BondA", 116.92, 3, Date(15,August,2003).serialNumber(), Date(15,August,2013).serialNumber(), "Following", "USD:Govt"); 
			std::string tradeA =  qlProxy.ZeroCouponBond("Mkt_", "Cache_", "tradeA", bondA, bcurve, 100, 0, 0);
			std::string resA = qlProxy.MarketValueTrade("Mkt_", "Cache_","tradeA", "NPV,CleanPrice,DirtyPrice,AccruedAmount,PreviousCouponRate,NextCouponRate,YieldAct360Annual");
			
			std::string bondB = qlProxy.FixedRateBondBuild("Mkt_", "BondB", 0.045, 0, "Semiannual", 100, 3, Date(15, May, 2007).serialNumber(), Date(15,May,2017).serialNumber(),"Act/Act:Bond","Unadjusted","Unadjusted","ModifiedFollowing", "USD:Govt"); 
			std::string tradeB =  qlProxy.FixedRateBond("Mkt_", "Cache_", "tradeB", bondB, bcurve, 100, 0, 0);
			std::string resB = qlProxy.MarketValueTrade("Mkt_", "Cache_","tradeB", "NPV,CleanPrice,DirtyPrice,AccruedAmount,PreviousCouponRate,NextCouponRate,YieldAct360Annual");
			
			std::string bondC = qlProxy.FloatingRateBondBuild("Mkt_", "BondC", 0.001, bcurve, "USDLibor3M", "Quarterly", 100, 3, Date(21, October, 2005).serialNumber(), Date(21, October, 2010).serialNumber(), "Act/360", "Unadjusted", "Unadjusted", "ModifiedFollowing", "USD:NYSE"); 
			std::string tradeC =  qlProxy.FloatingRateBond("Mkt_", "Cache_", "tradeC", bondC, bcurve, 100, 0, 0);
			std::string resC = qlProxy.MarketValueTrade("Mkt_", "Cache_","tradeC", "NPV,CleanPrice,DirtyPrice,AccruedAmount,PreviousCouponRate,NextCouponRate,YieldAct360Annual");

			if(resA == "tradeId,NPV,CleanPrice,DirtyPrice,AccruedAmount,PreviousCouponRate,NextCouponRate,YieldAct360Annual;tradeA,100.922,100.922,100.922,0,0,N/A,0.0300006")
			if(resB == "tradeId,NPV,CleanPrice,DirtyPrice,AccruedAmount,PreviousCouponRate,NextCouponRate,YieldAct360Annual;tradeB,107.668,106.128,107.668,1.54076,0.045,0.045,0.0364756")
			if(resC == "tradeId,NPV,CleanPrice,DirtyPrice,AccruedAmount,PreviousCouponRate,NextCouponRate,YieldAct360Annual;tradeC,102.359,101.797,102.359,0.562113,0.0288625,N/A,0.0220096")
			{
				return 1;
			}
	
	} 
	catch (std::exception& e) 
	{
		std::cerr << e.what() << std::endl; 
	} 
	catch (...) 
	{
		std::cerr << "unknown error" << std::endl;
	}

	return 0;
}

int TestCDS()
{
	try 
	{

		Calendar calendar = TARGET();
		Date todaysDate(15, May, 2007);
		todaysDate = calendar.adjust(todaysDate);

		/*
			In Lehmans Brothers "guide to exotic credit derivatives"
			p. 32 there's a simple case, zero flat curve with a flat CDS
			curve with constant market spreads of 150 bp and RR = 50%
			corresponds to a flat 3% hazard rate. The implied 1-year
			survival probability is 97.04% and the 2-years is 94.18%
		*/

		ql qlProxy;

		std::string mkt = qlProxy.MarketSet("Mkt_", todaysDate.serialNumber());

		std::string discCurve = qlProxy.FlatForwardCurve("Mkt_", "FlatForwardCurve", "", todaysDate.serialNumber(), 0.01, "Act/365:Fixed");
		std::stringstream spreads;
		//build spreads
		spreads <<  qlProxy.CdsSpread("Mkt_", "FinPlus3M", 0.015, 0.5, "3M", 0,discCurve, "Quarterly", "Act/365:Fixed", "Following", "TGT") << ",";
		spreads <<  qlProxy.CdsSpread("Mkt_", "FinPlus1Y", 0.015, 0.5, "1Y", 0,discCurve, "Quarterly", "Act/365:Fixed", "Following", "TGT") << ",";
		spreads <<  qlProxy.CdsSpread("Mkt_", "FinPlus2Y", 0.015, 0.5, "2Y", 0,discCurve, "Quarterly", "Act/365:Fixed", "Following", "TGT");
		
		std::string defaultCurve1 = qlProxy.DefaultCurve("Mkt_", "DefaultCurve1", discCurve,  todaysDate.serialNumber(), spreads.str(), 0.5,  "Act/365:Fixed", "TGT");

		std::string cds3m = qlProxy.CreditDefaultSwap("Mkt_",  "Cache_", "cds3m", "DefaultCurve1", 0.0150, "Sell",  1000000.0, 39217, 39309, "Quarterly",  "Unadjusted", "Following", "Act/365:Fixed", "TGT");
		std::string cds6m = qlProxy.CreditDefaultSwap("Mkt_",  "Cache_","cds6m", "DefaultCurve1", 0.0150, "Sell",  1000000.0, 39217, 39401, "Quarterly",  "Unadjusted", "Following", "Act/365:Fixed", "TGT");
		std::string cds1y = qlProxy.CreditDefaultSwap("Mkt_",  "Cache_", "cds1y", "DefaultCurve1",  0.0150, "Sell",  1000000.0, 39217, 39583, "Quarterly",  "Unadjusted", "Following", "Act/365:Fixed", "TGT");
		std::string cds2y = qlProxy.CreditDefaultSwap("Mkt_",  "Cache_", "cds2y", "DefaultCurve1", 0.0150, "Sell",  1000000.0, 39217, 39948, "Quarterly",  "Unadjusted", "Following", "Act/365:Fixed", "TGT");
		
		std::string resCds3m = qlProxy.MarketValueTrade("Mkt_",  "Cache_", cds3m, "FairSpread,NPV,DefaultLegNPV,CouponLegNPV");
		std::string resCds6m = qlProxy.MarketValueTrade("Mkt_",  "Cache_", cds6m, "FairSpread,NPV,DefaultLegNPV,CouponLegNPV");
		std::string resCds1y = qlProxy.MarketValueTrade("Mkt_",  "Cache_", cds1y, "FairSpread,NPV,DefaultLegNPV,CouponLegNPV");
		std::string resCds2y = qlProxy.MarketValueTrade("Mkt_",  "Cache_", cds2y, "FairSpread,NPV,DefaultLegNPV,CouponLegNPV");

		if(resCds3m == "tradeId,FairSpread,NPV,DefaultLegNPV,CouponLegNPV;cds3m,0.015,-8.71396e-008,-5218.16,5218.16")
		if(resCds6m == "tradeId,FairSpread,NPV,DefaultLegNPV,CouponLegNPV;cds6m,0.0150001,-0.050253,-8882.88,8882.83")
		if(resCds1y == "tradeId,FairSpread,NPV,DefaultLegNPV,CouponLegNPV;cds1y,0.015,-1.82434e-007,-16142.9,16142.9")
		if(resCds2y == "tradeId,FairSpread,NPV,DefaultLegNPV,CouponLegNPV;cds2y,0.015,-2.35155e-007,-30195.6,30195.6")
		{
			return 1;
		}
    
	} 
	catch (std::exception& e) 
	{
		std::cerr << e.what() << std::endl; 
	} 
	catch (...) 
	{
		std::cerr << "unknown error" << std::endl;
	}

	return 0;
}

int TestSwap()
{
	try 
	{
		//test swaps
		Date settlementDate(22, September, 2004);
		Calendar calendar = TARGET();
		settlementDate = calendar.adjust(settlementDate);
		
		Date todaysDate = calendar.advance(settlementDate, -2, Days);
		ql qlProxy;

		std::string mkt = qlProxy.MarketSet("Mkt_", todaysDate.serialNumber());

		std::string indx = qlProxy.Index("Mkt_", "EURCurve", "Euribor6M", "Euribor", "6M", "");

		//build three different peicewiseYieldCurves 1.DepoSwap 2. DepoFRASwap note should be able to use for bonds cds etc
		//"Depo,Rate,1,Weeks,0.0382;Depo,Rate,1,Months,0.0372;Depo,Rate,3,Months,0.0363;Depo,Rate,6,Months,0.0353;Depo,Rate,9,Months,0.0348;Depo,Rate,1,Years,0.0345;Swap,Rate,2,Years,0.037125;Swap,Rate,3,Years,0.0398;Swap,Rate,5,Years,0.0443;Swap,Rate,10,Years,0.05165;Swap,Rate,15,Years,0.055175"
		//"Depo,Rate,1,Weeks,0.0382;Depo,Rate,1,Months,0.0372;Depo,Rate,3,Months,0.0363;FRA,Rate,3,6,0.037125;FRA,Rate,6,9,0.037125;FRA,Rate,6,12,0.037125;Swap,Rate,2,Years,0.037125;Swap,Rate,3,Years,0.0398;Swap,Rate,5,Years,0.0443;Swap,Rate,10,Years,0.05165;Swap,Rate,15,Years,0.055175"
		//"Depo,Rate,1,Weeks,0.0382;Depo,Rate,1,Months,0.0372; Fut,Real,1,IMM,96.2875;Fut,Real,2,IMM,96.7875;Fut,Real,3,IMM,96.9875;Fut,Real,4,IMM,96.6875;Fut,Real,5,IMM,96.4875;Fut,Real,6,IMM,96.3875;Fut,Real,7,IMM,96.2875;Fut,Real,8,IMM,96.0875;Swap,Rate,3,Years,0.0398;Swap,Rate,5,Years,0.0443;Swap,Rate,10,Years,0.05165;Swap,Rate,15,Years,0.055175"

		std::stringstream rates;
		//build depo rates
		rates << qlProxy.DepoRate("Mkt_","EURDepo1W", 0.0382, "1W", 2, "Act/360", "ModifiedFollowing", "TGT") << ",";
		rates << qlProxy.DepoRate("Mkt_","EURDepo1M", 0.0372, "1M", 2, "Act/360", "ModifiedFollowing", "TGT") << ",";
		//build fut rates
		int immDate = qlProxy.NextImmDate(todaysDate.serialNumber() + 1);rates << qlProxy.FutRate("Mkt_","EURFut1", 96.2875, immDate, 3, "Act/360", "ModifiedFollowing", "TGT") << ","; 
		immDate = qlProxy.NextImmDate(immDate + 1);	rates << qlProxy.FutRate("Mkt_","EURFut2", 96.7875, immDate, 3, "Act/360", "ModifiedFollowing", "TGT") << ","; 
		immDate = qlProxy.NextImmDate(immDate + 1);	rates << qlProxy.FutRate("Mkt_","EURFut3", 96.9875, immDate, 3, "Act/360", "ModifiedFollowing", "TGT") << ","; 
		immDate = qlProxy.NextImmDate(immDate + 1);	rates << qlProxy.FutRate("Mkt_","EURFut4", 96.6875, immDate, 3, "Act/360", "ModifiedFollowing", "TGT") << ","; 
		immDate = qlProxy.NextImmDate(immDate + 1);	rates << qlProxy.FutRate("Mkt_","EURFut5", 96.4875, immDate, 3, "Act/360", "ModifiedFollowing", "TGT") << ","; 
		immDate = qlProxy.NextImmDate(immDate + 1);	rates << qlProxy.FutRate("Mkt_","EURFut6", 96.3875, immDate, 3, "Act/360", "ModifiedFollowing", "TGT") << ","; 
		immDate = qlProxy.NextImmDate(immDate + 1);	rates << qlProxy.FutRate("Mkt_","EURFut7", 96.2875, immDate, 3, "Act/360", "ModifiedFollowing", "TGT") << ","; 
		immDate = qlProxy.NextImmDate(immDate + 1);	rates << qlProxy.FutRate("Mkt_","EURFut8", 96.0875, immDate, 3, "Act/360", "ModifiedFollowing", "TGT") << ",";
		//build swap rates
		rates << qlProxy.SwapRate("Mkt_","EURSwap3Y", 0.0398, "3Y", 3, 0, "Euribor6M", "Annual", "Euro30/360","Unadjusted","TGT") << ",";
		rates << qlProxy.SwapRate("Mkt_","EURSwap5Y", 0.0443, "5Y", 3, 0, "Euribor6M", "Annual", "Euro30/360","Unadjusted","TGT") << ",";
		rates << qlProxy.SwapRate("Mkt_","EURSwap10Y", 0.05165, "10Y", 3, 0, "Euribor6M", "Annual", "Euro30/360","Unadjusted","TGT") << ",";
		rates << qlProxy.SwapRate("Mkt_","EURSwap15Y", 0.055175, "15Y", 3, 0, "Euribor6M", "Annual", "Euro30/360","Unadjusted","TGT");
		//build curve
		std::string curve1 = qlProxy.YieldCurve("Mkt_", "EURCurve", "EURCurve", settlementDate.serialNumber(), rates.str(), "Act/Act:ISDA", 0, "TGT");
	
		//create basis trade and value
		std::string spot5YearBasisSwap1 = qlProxy.BasisSwap("Mkt_", "Cache1_","spot5YearBasisSwap1", 1000000.0, settlementDate.serialNumber(), (settlementDate + 5*Years).serialNumber(),"Payer", "EURCurve", "Euribor6M", 0.0, "Semiannual",  "ModifiedFollowing", "Act/360", "EURCurve", "Euribor6M", 0.0, "Annual",  "Unadjusted", "Euro30/360", "TGT");
		std::string spot5YearBasisSwap2 = qlProxy.BasisSwap("Mkt_", "Cache1_","spot5YearBasisSwap2", 1000000.0, settlementDate.serialNumber(), (settlementDate + 5*Years).serialNumber(),"Receiver",	"EURCurve", "Euribor6M", 0.0, "Annual",  "Unadjusted", "Euro30/360","EURCurve", "Euribor6M", 0.0, "Semiannual",  "ModifiedFollowing", "Act/360","TGT");
		std::string spot5YearSwap1 = qlProxy.VanillaSwap("Mkt_", "Cache1_","spot5YearSwap1", "EURCurve", -1000000.0, settlementDate.serialNumber(), (settlementDate + 5*Years).serialNumber(), 0.04,"Receiver", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360","TGT");
		std::string spot5YearSwap2 = qlProxy.VanillaSwap("Mkt_", "Cache1_","spot5YearSwap2", "EURCurve", 1000000.0, settlementDate.serialNumber(), (settlementDate + 5*Years).serialNumber(), 0.04,"Receiver", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360","TGT");
		std::string allTrades1 = qlProxy.MarketValueTrades("Mkt_", "Cache1_", "NPV,FloatingLegNPV,FloatingLeg2NPV");

		//create fixed, float  and value
		std::string spot5FloatingLeg = qlProxy.FloatingLeg("Mkt_", "Cache2_","spot5FloatingLeg", 1000000.0, settlementDate.serialNumber(), (settlementDate + 5*Years).serialNumber(),"Payer", "EURCurve", "Euribor6M", 0.0, "Semiannual",  "ModifiedFollowing", "Act/360", "TGT");
		std::string spot5FixedLeg = qlProxy.FixedLeg("Mkt_", "Cache2_","spot5FixedLeg", "EURCurve", 1000000.0, settlementDate.serialNumber(), (settlementDate + 5*Years).serialNumber(),0.04, "Receiver", "Euribor6M", "Annual", "Unadjusted", "Euro30/360", "TGT");
		std::string spot5YearSwap3 = qlProxy.VanillaSwap("Mkt_", "Cache2_","spot5YearSwap", "EURCurve", 1000000.0, settlementDate.serialNumber(), (settlementDate + 5*Years).serialNumber(), 0.04,"Receiver", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360","TGT");
		std::string allTrades2 = qlProxy.MarketValueTrades("Mkt_", "Cache2_", "NPV,FloatingLegNPV,FixedLegNPV");

		//create one FRA  and value
		std::string fra = qlProxy.ForwardRateAgreement("Mkt_", "Cache3_", "fra", "EURCurve", 1000000.0, (settlementDate + 1*Months).serialNumber(), (settlementDate + 4*Months).serialNumber(), 0.04,"Receiver", "Euribor3M");
		std::string allTrades3 = qlProxy.MarketValueTrades("Mkt_", "Cache3_", "NPV,ForwardRate,ForwardValue,SpotValue");

		//create two trades
		std::string spot5YearSwap = qlProxy.VanillaSwap("Mkt_", "Cache_", "spot5YearSwap", "EURCurve", 1000000.0, settlementDate.serialNumber(), (settlementDate + 5*Years).serialNumber(), 0.04,"Payer", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360","TGT");
		std::string oneYearForward5YearSwap = qlProxy.VanillaSwap("Mkt_", "Cache_", "oneYearForward5YearSwap", "EURCurve", 1000000.0, calendar.advance(settlementDate, 1, Years).serialNumber(), (calendar.advance(settlementDate, 1, Years) + 5*Years).serialNumber(), 0.04, "Payer", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360","TGT");
		
		std::string spot5YearSwapValuation = qlProxy.MarketValueTrade("Mkt_", "Cache_", "spot5YearSwap","NPV,FairSpread,FairRate");
		std::string oneYearForward5YearSwapValuation = qlProxy.MarketValueTrade("Mkt_",  "Cache_", "oneYearForward5YearSwap","NPV,FairSpread,FairRate");

		if(spot5YearSwapValuation == "tradeId,NPV,FairSpread,FairRate;spot5YearSwap,19076.1,-0.00419258,0.0443" 
		&& oneYearForward5YearSwapValuation =="tradeId,NPV,FairSpread,FairRate;oneYearForward5YearSwap,40092.8,-0.00923433,0.0494846")
		{
			return 1;
		}

	} 
	catch (std::exception& e) 
	{
		std::cerr << e.what() << std::endl; 
	} 
	catch (...) 
	{
		std::cerr << "unknown error" << std::endl;
	}

	return 0;
}

int TestFra()
{
	//already done fras just no test back to demo yet
	return 0;
}

int TestSwaption()
{
	try 
	{
        Date todaysDate(15, February, 2002);
        Calendar calendar = TARGET();
        Date settlementDate(19, February, 2002);
        Settings::instance().evaluationDate() = todaysDate;

        // flat yield term structure impling 1x5 swap at 5%
       	ql qlProxy;
		std::string _mkt = qlProxy.MarketSet("Mkt_", todaysDate.serialNumber());
		std::string _rhTermStructure = qlProxy.FlatForwardCurve("Mkt_", "FlatCurve", "", settlementDate.serialNumber(), 0.04875825 , "Act/365:Fixed");

		std::string _indexSixMonths = qlProxy.Index("Mkt_", "FlatCurve", "Euribor6M", "Euribor", "6M", ""); 
   
		stringstream vSurf2; 
		vSurf2 << "Tenor,1Y,2Y,3Y,4Y,5Y;";
		vSurf2 << "1Y,0.1490,0.1340,0.1228,0.1189,0.1148;";
		vSurf2 << "2Y,0.1290,0.1201,0.1146,0.1108,0.1040;";
		vSurf2 << "3Y,0.1149,0.1112,0.1070,0.1010,0.0957;";
		vSurf2 << "4Y,0.1047,0.1021,0.0980,0.0951,0.1270;";
		vSurf2 << "5Y,0.1000,0.0950,0.0900,0.1230,0.1160";

		stringstream vSurf; // 1x5, 2x4, 3x3, 4x2, 5x1
		vSurf << "Tenor,1Y,2Y,3Y,4Y,5Y;";
		vSurf << "1Y,0.0,0.0,0.0,0.0,0.1148;";
		vSurf << "2Y,0.0,0.0,0.0,0.1108,0.0;";
		vSurf << "3Y,0.0,0.0,0.1070,0.0,0.0;";
		vSurf << "4Y,0.0,0.1021,0.0,0.0,0.0;";
		vSurf << "5Y,0.1000,0.0,0.0,0.0,0.0";

		std::string vG2 =  qlProxy.VolSurf("Mkt_", "FlatCurve", "VolSurfG2", vSurf.str(), "Euribor6M", "G2,6,16");
		std::string vHW1 =  qlProxy.VolSurf("Mkt_", "FlatCurve", "VolSurfHW1", vSurf.str(), "Euribor6M", "HW1");
		std::string vHW2 =  qlProxy.VolSurf("Mkt_", "FlatCurve", "VolSurfHW2", vSurf.str(), "Euribor6M", "HW2,30");
		std::string vBK =  qlProxy.VolSurf("Mkt_", "FlatCurve", "VolSurfBK", vSurf.str(), "Euribor6M", "BK,30");

		//std::string bv = qlProxy.ImpliedBlackVol("Mkt_", "VolSurfG2", "G2");
		
		std::string atmbsG2 = qlProxy.BermudanSwaption("Mkt_", "Cache_", "atmbsG2", "FlatCurve", "VolSurfG2", 1000.0, 37671, 39497, 0.050000005910246725, "Payer", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360", "TGT");
		std::string otmbsG2 = qlProxy.BermudanSwaption("Mkt_", "Cache_", "otmbsG2", "FlatCurve", "VolSurfG2", 1000.0, 37671, 39497, 0.060000007092296068, "Payer", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360", "TGT");
		std::string itmbsG2 = qlProxy.BermudanSwaption("Mkt_", "Cache_", "itmbsG2", "FlatCurve", "VolSurfG2", 1000.0, 37671, 39497, 0.040000004728197383, "Payer", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360", "TGT");
		
		std::string atmbsHW1 = qlProxy.BermudanSwaption("Mkt_", "Cache_", "atmbsHW1", "FlatCurve", "VolSurfHW1", 1000.0, 37671, 39497, 0.050000005910246725, "Payer", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360", "TGT");
		std::string otmbsHW1 = qlProxy.BermudanSwaption("Mkt_", "Cache_", "otmbsHW1", "FlatCurve", "VolSurfHW1", 1000.0, 37671, 39497, 0.060000007092296068, "Payer", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360", "TGT");
		std::string itmbsHW1 = qlProxy.BermudanSwaption("Mkt_", "Cache_", "itmbsHW1", "FlatCurve", "VolSurfHW1", 1000.0, 37671, 39497, 0.040000004728197383, "Payer", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360", "TGT");
	
		std::string atmbsHW2 = qlProxy.BermudanSwaption("Mkt_", "Cache_", "atmbsHW2", "FlatCurve", "VolSurfHW2", 1000.0, 37671, 39497, 0.050000005910246725, "Payer", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360", "TGT");
		std::string otmbsHW2 = qlProxy.BermudanSwaption("Mkt_", "Cache_", "otmbsHW2", "FlatCurve", "VolSurfHW2", 1000.0, 37671, 39497, 0.060000007092296068, "Payer", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360", "TGT");
		std::string itmbsHW2 = qlProxy.BermudanSwaption("Mkt_", "Cache_", "itmbsHW2", "FlatCurve", "VolSurfHW2", 1000.0, 37671, 39497, 0.040000004728197383, "Payer", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360", "TGT");
		
		std::string atmbsBK = qlProxy.BermudanSwaption("Mkt_", "Cache_", "atmbsBK", "FlatCurve", "VolSurfBK", 1000.0, 37671, 39497, 0.050000005910246725, "Payer", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360", "TGT");
		std::string otmbsBK = qlProxy.BermudanSwaption("Mkt_", "Cache_", "otmbsBK", "FlatCurve", "VolSurfBK", 1000.0, 37671, 39497, 0.060000007092296068, "Payer", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360", "TGT");
		std::string itmbsBK = qlProxy.BermudanSwaption("Mkt_", "Cache_", "itmbsBK", "FlatCurve", "VolSurfBK", 1000.0, 37671, 39497, 0.040000004728197383, "Payer", "Euribor6M", 0.0, "Annual", "Semiannual", "Unadjusted", "ModifiedFollowing", "Euro30/360", "Act/360", "TGT");

		std::string res = qlProxy.MarketValueTrades("Mkt_", "Cache_", "NPV");
		if(res == "tradeId,NPV;atmbsBK,13.0023;atmbsG2,14.1099;atmbsHW1,13.1368;atmbsHW2,13.158;itmbsBK,41.825;itmbsG2,42.609;itmbsHW1,42.3464;itmbsHW2,42.3643;otmbsBK,3.27513;otmbsG2,3.27081;otmbsHW1,2.61444;otmbsHW2,2.61496")
		{
			return 1;
		}
    } 
	catch (std::exception& e) 
	{
        std::cerr << e.what() << std::endl;
    } 
	catch (...) 
	{
        std::cerr << "unknown error" << std::endl;
	}

	return 0;
}

int TestRepo()
{
	try 
	{
        Date repoSettlementDate(14,February,2000);

		ql qlProxy;
		std::string _mkt = qlProxy.MarketSet("Mkt_", repoSettlementDate.serialNumber());

	    //bond curve from bond yield 0.10407665918108713
		std::string _bondCurve = qlProxy.FlatForwardCurve("Mkt_", "BondCurve", "", repoSettlementDate.serialNumber(), 0.10407665918108713, "30/360:BondBasis", "Semiannual", "Compounded");
		
		//repo curve 0.05 repo rate
		std::string _repoCurve = qlProxy.FlatForwardCurve("Mkt_", "RepoCurve", "",  repoSettlementDate.serialNumber(), 0.05, "Act/360", "Simple", "Annual");
		
		//bond
		std::string _bond = qlProxy.FixedRateBondBuild("Mkt_", "Bond", 0.08, 89.97693786, "Semiannual", 100, 0, Date(15,September,1995).serialNumber(), Date(15,September,2005).serialNumber(), "30/360:BondBasis", "Unadjusted", "Unadjusted","Unadjusted", "");
	
		//repo trade 91.5745 strike relates to cash amount
		std::string _repoTrade = qlProxy.Repo("Mkt_", "Cache_", "RepoTrade", "Bond", "RepoCurve", "BondCurve", 91.5745, 100, Date(14,February,2000).serialNumber(), Date(15,August,2000).serialNumber(), 0, "Act/360", "Unadjusted", "");
		
		//value repo trade
		std::string resRepoTrade = qlProxy.MarketValueTrade("Mkt_", "Cache_", "RepoTrade", "UnderlyingCleanPrice,UnderlyingDirtyPrice,UnderlyingSettlementAccrued,UnderlyingDeliveryAccrued,UnderlyingSpotIncome,UnderlyingFwdIncome,Strike,NPV,CleanFwdPrice,DirtyFwdPrice,ImpliedYield,MktRepoRate");

        if(resRepoTrade == "tradeId,UnderlyingCleanPrice,UnderlyingDirtyPrice,UnderlyingSettlementAccrued,UnderlyingDeliveryAccrued,UnderlyingSpotIncome,UnderlyingFwdIncome,Strike,NPV,CleanFwdPrice,DirtyFwdPrice,ImpliedYield,MktRepoRate;RepoTrade,89.9769,93.288,3.31111,3.33333,3.9834,4.08465,91.5745,-2.8066e-005,88.2411,91.5745,5.000063 % Actual/360 simple compounding,5.000000 % Actual/360 simple compounding")
		{
			return 1;
		}
       
    } 
	catch (std::exception& e) 
	{
        std::cerr << e.what() << std::endl;
    } 
	catch (...) 
	{
        std::cerr << "unknown error" << std::endl;
	}

	return 0;
}

